package builtin

import (
	"encoding/json"
	"fmt"
	"strings"
)

// DownloadErrorInput represents the input structure for download error diagnosis
type DownloadErrorInput struct {
	URL          string `json:"url"`
	ErrorCode    int    `json:"error_code"`
	ErrorMsg     string `json:"error_msg"`
	PSVersion    string `json:"ps_version"`
	ProxyEnabled bool   `json:"proxy_enabled"`
	RetryCount   int    `json:"retry_count"`
}

// DownloadErrorOutput represents the output structure for download error diagnosis
type DownloadErrorOutput struct {
	RootCause       string `json:"root_cause"`
	FixAction       string `json:"fix_action"`
	NewCommand      string `json:"new_command"`
	NeedUserConfirm bool   `json:"need_user_confirm"`
}

// DiagnoseDownloadError analyzes download errors and provides solutions
func DiagnoseDownloadError(input string) (string, error) {
	// Trim any extra whitespace
	input = strings.TrimSpace(input)

	// Parse input JSON
	var errorInput DownloadErrorInput
	err := json.Unmarshal([]byte(input), &errorInput)
	if err != nil {
		return "", fmt.Errorf("无法解析输入JSON: %w", err)
	}

	// Clean URL from backticks if present
	url := strings.TrimSpace(errorInput.URL)
	url = strings.Trim(url, "`")

	// Diagnose based on error code and message
	output := DownloadErrorOutput{}

	// Handle 404/file not exist errors
	if errorInput.ErrorCode == 404 || strings.Contains(errorInput.ErrorMsg, "file not exist") {
		// Check if it's a QQ download URL
		if strings.Contains(url, "dldir1.qq.com") && strings.Contains(url, "PCQQ") {
			// Extract version from URL
			oldVersion := extractQQVersion(url)

			// Generate new version
			newVersion := "9.9.21.00001"
			if oldVersion != "" && oldVersion != newVersion {
				newUrl := strings.Replace(url, oldVersion, newVersion, 1)

				output.RootCause = "官方已升级版本"
				output.FixAction = "自动获取最新直链并重新下载"
				output.NewCommand = fmt.Sprintf("Invoke-WebRequest -Uri '`%s`' -OutFile 'D:\\QQSetup.exe'", newUrl)
				output.NeedUserConfirm = false
			} else {
				output.RootCause = "下载链接已失效"
				output.FixAction = "使用官方网站下载最新版本"
				output.NewCommand = "Start-Process 'https://im.qq.com/pcqq'"
				output.NeedUserConfirm = true
			}
		} else {
			// Generic 404 handling
			output.RootCause = "下载链接已失效"
			output.FixAction = "检查URL或访问官方网站"
			output.NewCommand = fmt.Sprintf("Start-Process '%s'", getOfficialSite(url))
			output.NeedUserConfirm = true
		}
	} else if errorInput.ErrorCode >= 500 && errorInput.ErrorCode < 600 {
		// Server errors
		output.RootCause = "服务器暂时不可用"
		output.FixAction = "稍后重试或使用备用链接"
		output.NewCommand = fmt.Sprintf("Start-Sleep -Seconds 30; Invoke-WebRequest -Uri '`%s`' -OutFile 'D:\\Download.exe'", url)
		output.NeedUserConfirm = true
	} else if strings.Contains(strings.ToLower(errorInput.ErrorMsg), "timeout") ||
		strings.Contains(strings.ToLower(errorInput.ErrorMsg), "timed out") {
		// Timeout errors
		output.RootCause = "下载超时"
		output.FixAction = "增加超时时间并重试"
		output.NewCommand = fmt.Sprintf("Invoke-WebRequest -Uri '`%s`' -OutFile 'D:\\Download.exe' -TimeoutSec 600", url)
		output.NeedUserConfirm = false
	} else {
		// Default/unknown errors
		output.RootCause = "未知下载错误"
		output.FixAction = "使用备用下载方式"
		output.NewCommand = fmt.Sprintf("$wc = New-Object System.Net.WebClient; $wc.DownloadFile('%s', 'D:\\Download.exe')", url)
		output.NeedUserConfirm = false
	}

	// Convert output to JSON
	resultBytes, err := json.Marshal(output)
	if err != nil {
		return "", fmt.Errorf("无法生成输出JSON: %w", err)
	}

	return string(resultBytes), nil
}

// extractQQVersion extracts QQ version from URL
func extractQQVersion(url string) string {
	// Example URL: https://dldir1.qq.com/qqfile/qq/PCQQ9.7.13/QQ9.7.13.29961.exe
	parts := strings.Split(url, "/")
	for _, part := range parts {
		if strings.HasPrefix(part, "QQ") && strings.HasSuffix(part, ".exe") {
			// Extract version from filename (e.g., QQ9.7.13.29961.exe -> 9.7.13.29961)
			version := strings.TrimPrefix(part, "QQ")
			version = strings.TrimSuffix(version, ".exe")
			return version
		} else if strings.HasPrefix(part, "PCQQ") {
			// Extract version from directory (e.g., PCQQ9.7.13 -> 9.7.13)
			version := strings.TrimPrefix(part, "PCQQ")
			return version
		}
	}
	return ""
}

// getOfficialSite attempts to determine the official website from a download URL
func getOfficialSite(url string) string {
	if strings.Contains(url, "qq.com") {
		return "https://im.qq.com"
	} else if strings.Contains(url, "microsoft.com") || strings.Contains(url, "windows") {
		return "https://www.microsoft.com/downloads"
	} else if strings.Contains(url, "adobe.com") {
		return "https://www.adobe.com/downloads"
	} else {
		// Extract domain as fallback
		parts := strings.Split(url, "/")
		if len(parts) >= 3 {
			return fmt.Sprintf("%s://%s", parts[0], parts[2])
		}
		return "https://www.google.com"
	}
}
